#include "wall.h"

Wall::Wall(int width, int height, Type type, Neighbour neighbour, string neighbourRoom)
{

    this->setSize(width, height);
    this->setType(type);
    this->setNeighbour(neighbour);
    if (!neighbourRoom.empty())
        this->neighbourRoom = neighbourRoom;

    this->countMaxPower();
}

void Wall::setSize(int width, int height) {
    this->width = width;
    this->height = height;

    this->countSurface();
}

/*
 * EN
 * This function sets the wall type and its parametres.
 * Type type        - type
 *
 * CZ
 * Tato funkce zdi nastavi typ zdi a jeho parametry.
 * Type type        - typ
 *
 */
void Wall::setType(Type type) {
    this->type = type;

    switch(type) {
    case Outside:
        this->setMaxTemperatureDifference(maxTemperatureInside, minTemperatureOutside);
        this->totalCoefficient = materialOutside;
        this->complexCoefficient = coefficientOutside * this->surface;
        this->tauZero = tauZeroOutside;
        break;
    case Inside:
        this->setMaxTemperatureDifference(maxTemperatureInside, minTemperatureInside);
        this->totalCoefficient = materialInside;
        this->complexCoefficient = coefficientInside * this->surface;
        this->tauZero = tauZeroInside;
        break;
    case Ground:
        this->setMaxTemperatureDifference(maxTemperatureInside, minTemperatureGround);
        this->totalCoefficient = materialGround;
        this->complexCoefficient = coefficientGround * this->surface;
        this->tauZero = tauZeroGround;
        break;
    case Roof:
        this->setMaxTemperatureDifference(maxTemperatureInside, minTemperatureOutside);
        this->totalCoefficient = materialRoof;
        this->complexCoefficient = coefficientRoof * this->surface;
        this->tauZero = tauZeroRoof;
        break;
    default:
        this->setMaxTemperatureDifference(maxTemperatureInside, minTemperatureOutside);
        this->totalCoefficient = materialOutside;
        this->complexCoefficient = coefficientOutside * this->surface;
        this->tauZero = tauZeroOutside;
        break;
    }
}

/*
 * EN
 * This function sets the wall's outside temperature.
 * Neighbour neighbour      - neigbour
 *
 * CZ
 * Tato funkce zdi priradi vnejsi teplotu.
 * Neighbour neighbour      - soused
 *
 */
void Wall::setNeighbour(Neighbour neighbour) {
    this->neighbour = neighbour;

    switch(neighbour) {
    case OutsideN:
        this->neighbourTemperature = currentTemperatureOutsideN;
        break;
    case OutsideS:
        this->neighbourTemperature = currentTemperatureOutsideS;
        break;
    case OutsideW:
        this->neighbourTemperature = currentTemperatureOutsideW;
        break;
    case OutsideE:
        this->neighbourTemperature = currentTemperatureOutsideE;
        break;
    case Soil:
        this->neighbourTemperature = currentTemperatureSoil;
        break;
    case Sky:
        this->neighbourTemperature = currentTemperatureSky;
        break;
    default:
        this->neighbourTemperature = currentTemperatureOutsideN;
        break;
    }
}

/*
 * EN
 * This function calculates the max temperature difference.
 *
 * CZ
 * Tato funkce vypocita max teplotni rozdil.
 *
 */
void Wall::setMaxTemperatureDifference(double max, double min) {
    this->maxTemperatureDifference = max-min;
 }


/*
 * EN
 * This function calculates the wall surface.
 *
 * CZ
 * Tato funkce vypocita plochu zdi.
 *
 */
void Wall::countSurface() {
    // plocha = sirka * delka v metrech
    this->surface = static_cast<double>(static_cast<int>(this->width * this->height)) / 10000;
}

/*
 * EN
 * This function calculates the max power.
 *
 * CZ
 * Tato funkce vypocita max prikon.
 *
 */
void Wall::countMaxPower() {
    // max prikon je dan koeficienty, plochou a maximalnim teplotnim rozdilem
    this->maxPower = this->surface / this->totalCoefficient * this->maxTemperatureDifference;
}

/*
 * EN
 * This function calculates the new wall temperature using the simple model.
 * double input   - input power
 *
 * CZ
 * Tato funkce vypocita novou teplotu podle jednoducheho modelu.
 * double input   - vstupni prikon
 *
 */
void Wall::countNewTemperature(double input) {
    // T = Tsouseda + P * coef/ S
    this->currentTemperature = (input * this->maxPower) * this->totalCoefficient / this->surface + this->neighbourTemperature;
}

/*
 * EN
 * This function calculates the new wall temperature using the complex model.
 * double input   - input power
 *
 * CZ
 * Tato funkce vypocita novou teplotu podle rozsireneho modelu.
 * double input   - vstupni prikon
 *
 */
void Wall::countNewTemperatureComplex(double input) {

    // ubytek tepla Q = m*c*cas*deltaT/Tau0
    // m*c*cas
    this->heatLoss = this->complexCoefficient * timeInterval;
    // m*c*cas*deltaT
    this->heatLoss *= (this->currentTemperature - this->neighbourTemperature);
    // m*c*cas*deltaT/Tau0
    this->heatLoss /= this->tauZero;


    // energie, ktera pribyde
    double Pt = input * timeInterval;

    // E = energie - ubytek
    double totalEnergy = Pt - this->heatLoss;

    // prirustek teploty = E/mc
    double deltaTemp = totalEnergy / this->complexCoefficient;

    // nova = aktualni + prirustek
    this->newTemperature = this->currentTemperature + deltaTemp;
}

/*
 * EN
 * This function compares the string with preset wall types and returns the types.
 * string str   - string to be compared
 *
 * CZ
 * Tato funkce porovna retezec s prednastavenymi typy sten a vrati typ.
 * string str   - retezec k porovnani
 *
 */
Wall::Type Wall::getTypeFromStr(string str) {

    if (str.compare("Outside") == 0)
        return Outside;
    if (str.compare("Inside") == 0)
        return Inside;
    if (str.compare("Ground") == 0)
        return Ground;
    if (str.compare("Roof") == 0)
        return Roof;
    else
        return ErrorType;
}

/*
 * EN
 * This function compares the string with preset neighbours and returns the neighbour.
 * string str   - string to be compared
 *
 * CZ
 * Tato funkce porovna retezec s prednastavenymi sousedy a vrati souseda.
 * string str   - retezec k porovnani
 *
 */
Wall::Neighbour Wall::getNeighbourFromStr(string str) {


    if (str.compare("OutsideN") == 0)
        return OutsideN;
    if (str.compare("OutsideS") == 0)
        return OutsideS;
    if (str.compare("OutsideW") == 0)
        return OutsideW;
    if (str.compare("OutsideE") == 0)
        return OutsideE;
    if (str.compare("Soil") == 0)
        return Soil;
    if (str.compare("Sky") == 0)
        return Sky;
    else
        return ErrorNeighbour;
}
